home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
cgazv5n4.arc
/
HUNZIP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-23
|
5KB
|
160 lines
/*--- Listing 3 ------------------------- HUNZIP.C -------------
* Author: Anton Kruger, 5 October, 1990
*
* Copyright (c) Truda Software
*
* Source code may be freely used if authorship is acknowledged.
* Object code form may be used freely.
*
* Description: Contains routines to decompress a file that
* has been Huffman encoded with huff_zip.c
*
* Compilers: Turbo C++ 1.0, MSC 6.0
*
* Memory models: Any.
*
* Compile time switches:
* MAIN - if defined, a driver is provided
*-------------------------------------------------------------*/
#include <stdio.h>
#include "huff.h"
int huff_unzip(char *infile,char *outfile);
void error(char *s);
#if defined(MAIN)
#include <stdlib.h>
#endif
#if defined(MAIN)
/* A small driver for the Huffman decompression routine */
void main(int argc, char* argv[])
{
int i;
if (argc < 3)
error("Usage: HUNZIP infile outfile");
else{
i = huff_unzip(argv[1],argv[2]);
switch (i){
case -1:
error("could not open input file...");
break;
case -2:
error("could not open output file...");
break;
case -3:
error("input not a compressed file...");
break;
case -4:
error("input not a Huffman compressed file...");
break;
case -5:
error
("incorrect version of decompression program.");
break;
default:
;
}
}
exit(0);
}
#endif
int huff_unzip(char *infile,char *outfile)
{
/*
* This routine decodes a file "infile" that has been
* compressed by the companion routine, huff_zip.c.
* The output is written to the file "outfile".
*
* Return values:
* 0: normal return
* -1: could not open "infile"
* -2: could not open "outfile"
* -3: first ID byte invalid
* -4: second ID byte invalid
* -5: third ID byte invalid */
FILE *fp1;
FILE *fp2;
char byte;
int ib,node;
int root; /* Location of the root of
the Huffman tree */
unsigned long decoded; /* Counts the number of
decoded characters */
/* Open I/O files with enlarged buffers for efficiency */
if ((fp1 = fopen(infile,"r+b")) != NULL)
setvbuf(fp1,NULL,_IOFBF,BUFFER_SIZE);
else
return(-1);
if ((fp2 = fopen(outfile,"w+b")) != NULL)
setvbuf(fp2,NULL,_IOFBF,BUFFER_SIZE);
else{
fclose(fp1);
return(-2);
}
/* Check input file header for characters "CH1" */
if (getc(fp1) != 'C')
{ fclose(fp1); fclose(fp2); return(-3); }
if (getc(fp1) != 'H')
{ fclose(fp1); fclose(fp2); return(-4); }
if (getc(fp1) != '1')
{ fclose(fp1); fclose(fp2); return(-5); }
/* Read Huffman tree from input file */
fread(&nchars,sizeof(nchars),1,fp1);
fread(&root,sizeof(root),1,fp1);
fread(left_son,sizeof(left_son[1]),root+1,fp1);
fread(right_son,sizeof(right_son[1]),root+1,fp1);
fread(&nsymbols,sizeof(nsymbols),1,fp1);
fread(symbol,sizeof(symbol[1]),nsymbols,fp1);
/* Decompress the input file */
decoded = 0;
node = root;
while(decoded != nchars) {
/* Get a byte from compressed file */
byte = (char)getc(fp1);
/* Scan all bits in byte */
for (ib=7; ib>=0; ib--){
if (btest(byte,ib))
/* bit ib set ?, select left node */
node = left_son[node];
else
/* bit ib clear ?, select right node */
node = right_son[node];
/* Have reached a terminal node */
if (left_son[node] == NONE){
/* Write the decoded symbol */
putc(symbol[node],fp2);
if (++decoded == nchars)
/* Stop if all chars are decoded */
break;
else
/* Restart decoding at root of tree */
node = root;
}
}
}
/* Close files and return */
fclose(fp1);
fclose(fp2);
return(0);
}
void error(char *s)
{
fprintf(stderr,"Error: %s\n",s);
exit(-1);
}